using ASPApiDemo;
using ASPApiDemo.Common;
using ASPApiDemo.Common.Core;
// using ASPApiDemo.Common.Core;
using ASPApiDemo.Common.Option;
using ASPApiDemo.Extension;
using ASPApiDemo.IService;
using ASPApiDemo.Repository;
using ASPApiDemo.Service;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace ASPApiDemo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //【1】创建Web应用程序构建器实例，用于配置应用程序服务和中间件
            var builder = WebApplication.CreateBuilder(args);
            //如果项目比较复杂的话，建议使用Autofac来替换掉微软默认的DI容器
            builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory())
                .ConfigureContainer<ContainerBuilder>(builder =>
                {
                    // 可以单独注入
                    // builder.RegisterType<YourService>().As<IYourService>();
                    // 批量注入仓库层和服务层定义的服务
                    builder.RegisterModule<AutofacModuleRegister>();
                    // 批量注入controller并启用属性注入(可能用到api层的类，所以没有放到拓展层)
                    builder.RegisterModule<AutofacPropertityModule>();
                })
                .ConfigureAppConfiguration((hostingContext, config) =>
                    //【6】调用AppService的扩展方法，将配置选项静态管理类传入Configuration对象
                    hostingContext.Configuration.ConfigureApplication());
            //【6】为拿到webapplication
            builder.ConfigureApplication();
            // 统一注册配置选项
            builder.Services.AddAllOptionRegister();
            //【2】添加服务到依赖注入容器
            // 默认controller虽然构造函数的依赖是从容器里面取出来的，但是controller对象本身是直接new出来的
            // 那么的他的属性自然也无法自动从容器里面获取，即不支持属性注入
            // 将controller的实现方式由DefaultControllerActivator改成ServiceBasedControllerActivator就是从容器里创建了
            builder.Services.Replace(
                ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
            builder.Services.AddControllers();
            // 添加API探索器服务，用于生成API文档
            builder.Services.AddEndpointsApiExplorer();
            // 添加Swagger生成服务，用于生成OpenAPI规范文档
            builder.Services.AddSwaggerGen();
            // 添加AutoMapper服务，用于对象映射
            builder.Services.AddAutoMapper(typeof(AutoMapperConfig));
            AutoMapperConfig.RegisterAutoMapper();
            // 添加AppSettings服务，用于获取配置
            // 封装了获取配置的方法(json文件的内容在host初始化时候会放到Configuration对象中)
            builder.Services.AddSingleton(new AppSettings(builder.Configuration));
            // 添加自定义服务，注册IBaseRepository接口和BaseRepository实现类
            // 这一部分我们放到Autofac注入了，没使用默认的DI注入
            //builder.Services.AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>));
            //builder.Services.AddScoped(typeof(IBaseService<,>), typeof(BaseService<,>));
            // Redis缓存和Memory缓存服务都是实现了IDistributedCache。
            // Caching是对默认的缓存服务的封装
            builder.Services.AddCacheSetup();
            //【3】构建Web应用程序实例，完成服务注册，服务要在build之前注册
            var app = builder.Build();
            //将App存到自定义全局静态单例中
            //【6】方便我们直接拿到容器中的服务。而不是通过依赖注入的方式。
            app.ConfigureApplication();
            //【6】执行启动设置,将AppService的ISRun标志设为True，这样才可以让外部真正拿到容器
            app.UseApplicationSetup();
            //【4】添加中间件，配置HTTP请求处理管道
            // 检查是否处于开发环境
            if (app.Environment.IsDevelopment())
            {
                // 启用Swagger中间件，生成API规范文档
                app.UseSwagger();
                // 启用SwaggerUI中间件，提供API文档的Web界面
                app.UseSwaggerUI();
            }

            // 添加授权中间件，处理身份验证和授权
            app.UseAuthorization();
            // 添加控制器路由中间件，将HTTP请求映射到相应的控制器和操作方法
            app.MapControllers();
            //【5】启动应用程序，开始监听HTTP请求
            app.Run();
        }
    }
}